Last compiled on October, 2025


R Sienna example:

rm(list = ls())

fpackage.check <- function(packages) {
    lapply(packages, FUN = function(x) {
        if (!require(x, character.only = TRUE)) {
            install.packages(x, dependencies = TRUE)
            library(x, character.only = TRUE)
        }
    })
}

fsave <- function(x, file = NULL, location = "./data/processed/") {
    ifelse(!dir.exists("data"), dir.create("data"), FALSE)
    ifelse(!dir.exists("data/processed"), dir.create("data/processed"), FALSE)
    if (is.null(file))
        file = deparse(substitute(x))
    datename <- substr(gsub("[:-]", "", Sys.time()), 1, 8)
    totalname <- paste(location, datename, file, ".rda", sep = "")
    save(x, file = totalname)  #need to fix if file is reloaded as input name, not as x. 
}

fload <- function(filename) {
    load(filename)
    get(ls()[ls() != "filename"])
}

fshowdf <- function(x, ...) {
    knitr::kable(x, digits = 2, "html", ...) %>%
        kableExtra::kable_styling(bootstrap_options = c("striped", "hover")) %>%
        kableExtra::scroll_box(width = "100%", height = "300px")
}

colorize <- function(x, color) {
    sprintf("<span style='color: %s;'>%s</span>", color, x)
}
packages = c("RSiena", "devtools", "igraph")
fpackage.check(packages)
# devtools::install_github('JochemTolsma/RsienaTwoStep', build_vignettes=TRUE)
packages = c("RsienaTwoStep")
fpackage.check(packages)

NEED DATA - use build in datasets from RSIENNA ?s501 Is adjacency matrix for network type 1. Goal: Follow steps in 7.1 for different data:

Step 1. Define data

Dependent variable: ties

fpackage.check(packages)
[[1]]
NULL

Inspect networks. Remove NAs, make sure diagonal. Need to see binary (not weighted)

Put networks in an array


dim(s501) #says 50x50: 50 rows, 50 columns in data. 

nets <- array (data = c(s501, s502), dim = c(dim(s501), 2)) #
c(dim(s501),2)

# dimensions of array are number of columns and number of rows 

could replace this with data set from last week

Define dependent - and independent - variable

c(dim(s501),2)
[1] 50 50  2

Now combine into dataset - if use Rsiena, need this.

alcohol <- s50a[,1]alcohol
Error: unexpected symbol in "alcohol <- s50a[,1]alcohol"

Now can look at myeff - look at starting values - has density of two networks, reciprocity

Want much more statistics for model, though!!

Step 2:

Can see all effects that could include in the dataset. Which is a lot. And this is a simple dataset. and yeah, its huge. Also can see that the type depends on weight function (evaluation (), endowment (), and creation ())

Example. Jochem wants to make tie with Jos. Jochem’s consideration to make a tie with Jos could be different than consideration to maintain a tie, could be different that decistions to break a tie. Can’t estimate all three. Evalution: mechanisms the same for making as breaking, endowment = maintaining, creation = if there are none then what is the cost.

In this course: just use evaluation function. Assume mechanisms and functions to make/break ties are similar. include degree for evaluation. But what are all these effects? - should be able to calculate statistic for each effect for an ego in a network… Mathematical formula in chapter 12.

myeff
  effectName               include fix   test  initialValue parm
1 basic rate parameter net TRUE    FALSE FALSE    4.69604   0   
2 outdegree (density)      TRUE    FALSE FALSE   -1.48852   0   
3 reciprocity              TRUE    FALSE FALSE    0.00000   0   

Make sure to understand out degree and reciprocity effects - statistics - will play around with this next week. Need to think of theory for which statistics are relevant. - Look at literature for statistics, think about it, play and see if effects exists - how work in reality? propose idea, write notation, see if effect exists in manual, etc. Lots of notation because everyone is looking for their own effects. - need to include more effects if what to.

Step 3: Look at intial data

print01Report(mydata)

# gives initial description of data 
# reading network variables , covariates, density measures/changes in networks, tie changes between subsequent observations... calculate how much networks changed over time. 
# dont use balance calculation 

Step 4: Add effects

myeff <- includeEffects(myeff, isolateNet, inPop, outAct)

#outAct - outdegree related activity 

outAct - look at the number of times I have and square that: especially the people that have a lot of ties will send a lot of ties. - evaluation function of tie1 0 ties, and tie1 4 ties - then at t2 people who have ties are more likely to send more ties

We know tie distributions are skewed, some people send a lot of ties and others dont.

inPop: in degree activity: people who receive a lot of in-degrees send a lot of out-degrees

isolateNet: people without a lot of indegree nets.

Can see that starting values are 0 – hypothesis testing

Step 5: Estimation

myeff <- includeEffects(myeff, isolateNet, inPop, outAct)
  effectNumber effectName            shortName  include fix   test  initialValue parm
1  78          indegree - popularity inPop      TRUE    FALSE FALSE          0   0   
2 106          outdegree - activity  outAct     TRUE    FALSE FALSE          0   0   
3 149          network-isolate       isolateNet TRUE    FALSE FALSE          0   0   

Now have first estimated Rsiena model!

if significant: more indegrees- more likely to send later. people with more out-degrees - more likely to send less (negative). isolate more likely to be alone.

Need to think of model that makes sense in this

REVIEWING RSIENA NOW - negative degree - density is less than .5 - interpretations - Mailing list for TOM

Afternoon: play with estimating our own models Nice to do with our own data - collaboration networks. Logic of RSIENA: took actor oriented approach - works if ties are directed. if undirected network, logic is different: the actor deciding on undirected tie is difficult. Advise: for now treat as undirected - and then evaluate tie. undirected tie by reach consensus, forced into concensus, etc - reciprocity matters less now.

Now play with it

Now - referencing web scraping site

fcolnet <- function(data = scholars, university = "RU", discipline = "sociology", waves = list(c(2015,
    2018), c(2019, 2023)), type = c("first")) {

    # step 1
    demographics <- do.call(rbind.data.frame, data$demographics)
    demographics <- demographics %>%
        mutate(Universiteit1.22 = replace(Universiteit1.22, is.na(Universiteit1.22), ""), Universiteit2.22 = replace(Universiteit2.22,
            is.na(Universiteit2.22), ""), Universiteit1.24 = replace(Universiteit1.24, is.na(Universiteit1.24),
            ""), Universiteit2.24 = replace(Universiteit2.24, is.na(Universiteit2.24), ""), discipline.22 = replace(discipline.22,
            is.na(discipline.22), ""), discipline.24 = replace(discipline.24, is.na(discipline.24), ""))

    sample <- which((demographics$Universiteit1.22 %in% university | demographics$Universiteit2.22 %in%
        university | demographics$Universiteit1.24 %in% university | demographics$Universiteit2.24 %in%
        university) & (demographics$discipline.22 %in% discipline | demographics$discipline.24 %in% discipline))

    demographics_soc <- demographics[sample, ]
    scholars_sel <- lapply(scholars, "[", sample)

    # step 2
    ids <- demographics_soc$au_id
    nwaves <- length(waves)
    nets <- array(0, dim = c(nwaves, length(ids), length(ids)), dimnames = list(wave = 1:nwaves, ids,
        ids))
    dimnames(nets)

    # step 3
    df_works <- tibble(works_id = unlist(lapply(scholars_sel$work, function(l) l$id)), works_author = unlist(lapply(scholars_sel$work,
        function(l) l$author), recursive = FALSE), works_year = unlist(lapply(scholars_sel$work, function(l) l$publication_year),
        recursive = FALSE))

    df_works <- df_works[!duplicated(df_works), ]

    # step 4
    if (type == "first") {
        for (j in 1:nwaves) {
            df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
                ]
            for (i in 1:nrow(df_works_w)) {
                ego <- df_works_w$works_author[i][[1]]$au_id[1]
                alters <- df_works_w$works_author[i][[1]]$au_id[-1]
                if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
                  nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
                }
            }
        }
    }

    if (type == "last") {
        for (j in 1:nwaves) {
            df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
                ]
            for (i in 1:nrow(df_works_w)) {
                ego <- rev(df_works_w$works_author[i][[1]]$au_id)[1]
                alters <- rev(df_works_w$works_author[i][[1]]$au_id)[-1]
                if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
                  nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
                }
            }
        }
    }

    if (type == "all") {
        for (j in 1:nwaves) {
            df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
                ]
            for (i in 1:nrow(df_works_w)) {
                egos <- df_works_w$works_author[i][[1]]$au_id
                if (sum(ids %in% egos) > 0) {
                  nets[j, which(ids %in% egos), which(ids %in% egos)] <- 1
                }
            }
        }
    }
    output <- list()
    output$data <- scholars_sel
    output$nets <- nets
    return(output)
}

Example in class from 10 October Siena dependent variable

# Step 1: load data
library(RSiena)
?sienaDependent #look for examples - script for how to run stuff 


# then check waves available
s501 #network at timepoint 1
s502 #network at timepoint 2
s503 #network at timepoint 


mynet1 <- sienaDependent(array(c(s501, s502, s503), dim=c(50, 50, 3)))
mybeh <- sienaDependent(s50a, type="behavior")

 # look for smoking and drinking behaviors

smoke <- s50s #time varying covariate. Time constant covar - varCovar
smoke <- varCovar(s50s)

mydata_example <- sienaDataCreate(mynet1, mybeh, smoke)



# Step 2: look at data
#print report on data reports

print01Report(mydata_example)


# Step 3: add effects 
myeff_example <- getEffects(mydata_example)
myeff_example



myeff_example <- includeEffects(myeff_example, unequalX, name="mynet1", interaction1 = "smoke")
myeff_example


#make algorithm to then estimate it
algo_ex <- sienaAlgorithmCreate(projname = "test_ex")
answer_ex <- siena07(algo_ex, data=mydata_example, effects=myeff_example, returnDeps = TRUE)

answer_ex


#does it change if dependent X 
myeff_example <- includeEffects(myeff_example, unequalX, name="mynet1", interaction1 = "mybeh") #name = network dependent variable, interaction 1 is covariate (smoking) - if have multiple netowrks, then could have unequalX with respect to X. We replaced smoke with my behavior, and rerun the siena model. This is an algorithm, can ask RSiena to reference previous result with 'prevans=ANS' after returnDepts = TRUE
answer_ex <- siena07(algo_ex, data=mydata_example, effects=myeff_example, returnDeps = TRUE)

answer_ex
# looking at results, mybeh = drinking -- ego less likely to spend time with people who drink more or less than them. ego also less likely to spend time with people who smoke more or less, to a lesser extent. Can use unequalX for dependent variables and covariates. key difference in estimation procedure: 
# we are also modeling behavioral results - behavior changing over time, simulated via ministep logic (one step up or down). The crucial difference: during the algorithm 
#If count statistic for smoke, then between time point 1 and 2 we use value from timepoint 1. between 2-3, use time point 2. But within the variable, the ego level behavior is changing. is not using the value as observed at t1 - it is using the value as is currently simulated. 





#could exclude variable to then include as covariate effect. 

mybeh <- sienaDependent(s50a, type="behavior") #defined as dependent variable 
drinking <- varCovar(s50a) #defined as covariate variable 

#update data object: 
mydata_example <- sienaDataCreate(mynet1, mybeh, drinking, smoke)


#and effects object: 
myeff_example <- includeEffects(myeff_example, unequalX, name="mynet1", interaction1 = "smoke")

myeff_example <- includeEffects(myeff_example, unequalX, name="mynet1", interaction1 = "drinking")

algo_ex2 <- sienaAlgorithmCreate(projname = "test_ex")

answer_ex <- siena07(algo_ex2, data=mydata_example, effects=myeff_example, returnDeps = TRUE)
answer_ex

#then the network dynamics change 
# interpretation of the rate constant - the average amount of ministeps each ego is making between the two observations

#behavioral dynamics: 
# the rate constant: the number of steps in the behavioral aspect 

#statistic for linear shape - linear shape effect - the value of the *centered* behavioral variable (average in the total sample). 
# if positive, try to increase behavior. effect is z1 (zed score), with the options of 1, 0, or -1. behavior increases because positively evaluates 1 more than 0, more than -1. At some point, though, behavior will stop increasing - that is z2 (squared!). so, parameter moderates itself with time?? 

# these are the minimum effects to include, because it predicts mean value observe in dataset. 2 parameters - estimate mean behavior. based on model results, what is the mean value. 

# behavioral variables in dataset - everything observed that changes. ex., position (functie), citations, interdisciplinarity score. Problem: is time window large enought to see change? and over time, behavioral variable is only changing - which then must be calculated as continuous depended variable. 
LS0tDQp0aXRsZTogInJzaWVuYSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyLCBnbG9iYWxzZXR0aW5ncywgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZSd9DQpsaWJyYXJ5KGtuaXRyKQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpvcHRzX2NodW5rJHNldCh0aWR5Lm9wdHM9bGlzdCh3aWR0aC5jdXRvZmY9MTAwKSx0aWR5PVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLGNvbW1lbnQgPSAiIz4iLCBjYWNoZT1UUlVFLCBjbGFzcy5zb3VyY2U9YygidGVzdCIpLCBjbGFzcy5vdXRwdXQ9YygidGVzdDIiKSkNCm9wdGlvbnMod2lkdGggPSAxMDApDQpyZ2w6OnNldHVwS25pdHIoKQ0KDQoNCmNvbG9yaXplIDwtIGZ1bmN0aW9uKHgsIGNvbG9yKSB7c3ByaW50ZigiPHNwYW4gc3R5bGU9J2NvbG9yOiAlczsnPiVzPC9zcGFuPiIsIGNvbG9yLCB4KSB9DQoNCg0KYGBgDQoNCmBgYHtyIGtsaXBweSwgZWNobz1GQUxTRSwgaW5jbHVkZT1UUlVFfQ0Ka2xpcHB5OjprbGlwcHkocG9zaXRpb24gPSBjKCd0b3AnLCAncmlnaHQnKSkNCiNrbGlwcHk6OmtsaXBweShjb2xvciA9ICdkYXJrcmVkJykNCiNrbGlwcHk6OmtsaXBweSh0b29sdGlwX21lc3NhZ2UgPSAnQ2xpY2sgdG8gY29weScsIHRvb2x0aXBfc3VjY2VzcyA9ICdEb25lJykNCmBgYA0KDQpMYXN0IGNvbXBpbGVkIG9uIGByIGZvcm1hdChTeXMudGltZSgpLCAnJUIsICVZJylgDQoNCjxicj4NCg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCg0KDQoNCg0KIyBSIFNpZW5uYSBleGFtcGxlOiANCg0KDQpgYGB7cn0NCnJtKGxpc3QgPSBscygpKQ0KDQpmcGFja2FnZS5jaGVjayA8LSBmdW5jdGlvbihwYWNrYWdlcykgew0KICAgIGxhcHBseShwYWNrYWdlcywgRlVOID0gZnVuY3Rpb24oeCkgew0KICAgICAgICBpZiAoIXJlcXVpcmUoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcyh4LCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICAgICAgICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogICAgICAgIH0NCiAgICB9KQ0KfQ0KDQpmc2F2ZSA8LSBmdW5jdGlvbih4LCBmaWxlID0gTlVMTCwgbG9jYXRpb24gPSAiLi9kYXRhL3Byb2Nlc3NlZC8iKSB7DQogICAgaWZlbHNlKCFkaXIuZXhpc3RzKCJkYXRhIiksIGRpci5jcmVhdGUoImRhdGEiKSwgRkFMU0UpDQogICAgaWZlbHNlKCFkaXIuZXhpc3RzKCJkYXRhL3Byb2Nlc3NlZCIpLCBkaXIuY3JlYXRlKCJkYXRhL3Byb2Nlc3NlZCIpLCBGQUxTRSkNCiAgICBpZiAoaXMubnVsbChmaWxlKSkNCiAgICAgICAgZmlsZSA9IGRlcGFyc2Uoc3Vic3RpdHV0ZSh4KSkNCiAgICBkYXRlbmFtZSA8LSBzdWJzdHIoZ3N1YigiWzotXSIsICIiLCBTeXMudGltZSgpKSwgMSwgOCkNCiAgICB0b3RhbG5hbWUgPC0gcGFzdGUobG9jYXRpb24sIGRhdGVuYW1lLCBmaWxlLCAiLnJkYSIsIHNlcCA9ICIiKQ0KICAgIHNhdmUoeCwgZmlsZSA9IHRvdGFsbmFtZSkgICNuZWVkIHRvIGZpeCBpZiBmaWxlIGlzIHJlbG9hZGVkIGFzIGlucHV0IG5hbWUsIG5vdCBhcyB4LiANCn0NCg0KZmxvYWQgPC0gZnVuY3Rpb24oZmlsZW5hbWUpIHsNCiAgICBsb2FkKGZpbGVuYW1lKQ0KICAgIGdldChscygpW2xzKCkgIT0gImZpbGVuYW1lIl0pDQp9DQoNCmZzaG93ZGYgPC0gZnVuY3Rpb24oeCwgLi4uKSB7DQogICAga25pdHI6OmthYmxlKHgsIGRpZ2l0cyA9IDIsICJodG1sIiwgLi4uKSAlPiUNCiAgICAgICAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkgJT4lDQogICAgICAgIGthYmxlRXh0cmE6OnNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpDQp9DQoNCmNvbG9yaXplIDwtIGZ1bmN0aW9uKHgsIGNvbG9yKSB7DQogICAgc3ByaW50ZigiPHNwYW4gc3R5bGU9J2NvbG9yOiAlczsnPiVzPC9zcGFuPiIsIGNvbG9yLCB4KQ0KfQ0KYGBgDQoNCg0KDQpgYGB7cn0NCnBhY2thZ2VzID0gYygiUlNpZW5hIiwgImRldnRvb2xzIiwgImlncmFwaCIpDQpmcGFja2FnZS5jaGVjayhwYWNrYWdlcykNCiMgZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCdKb2NoZW1Ub2xzbWEvUnNpZW5hVHdvU3RlcCcsIGJ1aWxkX3ZpZ25ldHRlcz1UUlVFKQ0KcGFja2FnZXMgPSBjKCJSc2llbmFUd29TdGVwIikNCmZwYWNrYWdlLmNoZWNrKHBhY2thZ2VzKQ0KYGBgDQoNCk5FRUQgREFUQSAtIHVzZSBidWlsZCBpbiBkYXRhc2V0cyBmcm9tIFJTSUVOTkEgDQo/czUwMQ0KSXMgYWRqYWNlbmN5IG1hdHJpeCBmb3IgbmV0d29yayB0eXBlIDEuIEdvYWw6IEZvbGxvdyBzdGVwcyBpbiA3LjEgZm9yIGRpZmZlcmVudCBkYXRhOg0KDQojIFN0ZXAgMS4gRGVmaW5lIGRhdGENCkRlcGVuZGVudCB2YXJpYWJsZTogdGllcyANCg0KDQpgYGB7cn0NCnM1MDEgI25ldHdvcmsgYXQgdGltZXBvaW50IDENCnM1MDIgI25ldHdvcmsgYXQgdGltZXBvaW50IDINCmBgYA0KDQoNCkluc3BlY3QgbmV0d29ya3MuIFJlbW92ZSBOQXMsIG1ha2Ugc3VyZSBkaWFnb25hbC4gTmVlZCB0byBzZWUgYmluYXJ5IChub3Qgd2VpZ2h0ZWQpDQpgYGB7cn0NCg0KYGBgDQoNCg0KUHV0IG5ldHdvcmtzIGluIGFuIGFycmF5DQpgYGB7cn0NCg0KZGltKHM1MDEpICNzYXlzIDUweDUwOiA1MCByb3dzLCA1MCBjb2x1bW5zIGluIGRhdGEuIA0KDQpuZXRzIDwtIGFycmF5IChkYXRhID0gYyhzNTAxLCBzNTAyKSwgZGltID0gYyhkaW0oczUwMSksIDIpKSAjDQpjKGRpbShzNTAxKSwyKQ0KDQojIGRpbWVuc2lvbnMgb2YgYXJyYXkgYXJlIG51bWJlciBvZiBjb2x1bW5zIGFuZCBudW1iZXIgb2Ygcm93cyANCmBgYA0KIGNvdWxkIHJlcGxhY2UgdGhpcyB3aXRoIGRhdGEgc2V0IGZyb20gbGFzdCB3ZWVrIA0KIA0KIA0KRGVmaW5lIGRlcGVuZGVudCAtIGFuZCBpbmRlcGVuZGVudCAtIHZhcmlhYmxlDQpgYGB7cn0NCg0KbmV0IDwtIHNpZW5hRGVwZW5kZW50KG5ldHMpICNkZXBlbmRlbnQgdmFyaWFibGUgDQoNCiAgIyBpbmRlcGVuZGVudCB2YXJpYWJsZSAtIHM1MGEgLSB3ZSB3aWxsIHRha2UgZmlyc3Qgd2F5IA0KYWxjb2hvbCA8LSBzNTBhWywxXWFsY29ob2wNCiAjIGRvbid0IG5lZWQgd2F2ZSAyIC0ganVzdCBtb2RlbGluZyBhdCBpbmRlcGVuZGVudCB2YXJpYWJsZSwgaW5mbHVlbmNpbmcgYWxsIG1pbmlzdGVwcyBiZXR3ZWVuIHRpbWUgMSBhbmQgdGltZSAyIA0KYWxjb2hvbCANCiANCmFsY29ob2wgPC0gY29Db3ZhcihhbGNvaG9sKSMgYXQgYWN0b3IgbGV2ZWwgLSBtZWFuIGNlbnRlcmVkIC0gaXMgYSB0aW1lIGNvbnN0YW50IGNvVmFyaWF0ZSANCmBgYA0KDQpOb3cgY29tYmluZSBpbnRvIGRhdGFzZXQgLSBpZiB1c2UgUnNpZW5hLCBuZWVkIHRoaXMuIA0KYGBge3J9DQpteWRhdGEgPC0gc2llbmFEYXRhQ3JlYXRlKG5ldCwgYWxjb2hvbCkNCg0KbXllZmYgPC0gZ2V0RWZmZWN0cyhteWRhdGEpICNoYXZlIGEgbG9vayANCm15ZWZmDQpgYGANCk5vdyBjYW4gbG9vayBhdCBteWVmZiAtIGxvb2sgYXQgc3RhcnRpbmcgdmFsdWVzIC0gaGFzIGRlbnNpdHkgb2YgdHdvIG5ldHdvcmtzLCByZWNpcHJvY2l0eSANCg0KDQpXYW50IG11Y2ggbW9yZSBzdGF0aXN0aWNzIGZvciBtb2RlbCwgdGhvdWdoISEgDQoNCiMgU3RlcCAyOiANCkNhbiBzZWUgYWxsIGVmZmVjdHMgdGhhdCBjb3VsZCBpbmNsdWRlIGluIHRoZSBkYXRhc2V0LiBXaGljaCBpcyBhIGxvdC4gQW5kIHRoaXMgaXMgYSBzaW1wbGUgZGF0YXNldC4gYW5kIHllYWgsIGl0cyBodWdlLiBBbHNvIGNhbiBzZWUgdGhhdCB0aGUgdHlwZSBkZXBlbmRzIG9uIHdlaWdodCBmdW5jdGlvbiAoZXZhbHVhdGlvbiAoKSwgZW5kb3dtZW50ICgpLCBhbmQgY3JlYXRpb24gKCkpDQoNCkV4YW1wbGUuIEpvY2hlbSB3YW50cyB0byBtYWtlIHRpZSB3aXRoIEpvcy4gSm9jaGVtJ3MgY29uc2lkZXJhdGlvbiB0byBtYWtlIGEgdGllIHdpdGggSm9zIGNvdWxkIGJlIGRpZmZlcmVudCB0aGFuIGNvbnNpZGVyYXRpb24gdG8gbWFpbnRhaW4gYSB0aWUsIGNvdWxkIGJlIGRpZmZlcmVudCB0aGF0IGRlY2lzdGlvbnMgdG8gYnJlYWsgYSB0aWUuIENhbid0IGVzdGltYXRlIGFsbCB0aHJlZS4gRXZhbHV0aW9uOiBtZWNoYW5pc21zIHRoZSBzYW1lIGZvciBtYWtpbmcgYXMgYnJlYWtpbmcsIGVuZG93bWVudCA9IG1haW50YWluaW5nLCBjcmVhdGlvbiA9IGlmIHRoZXJlIGFyZSBub25lIHRoZW4gd2hhdCBpcyB0aGUgY29zdC4gDQoNCkluIHRoaXMgY291cnNlOiBqdXN0IHVzZSBldmFsdWF0aW9uIGZ1bmN0aW9uLiBBc3N1bWUgbWVjaGFuaXNtcyBhbmQgZnVuY3Rpb25zIHRvIG1ha2UvYnJlYWsgdGllcyBhcmUgc2ltaWxhci4gaW5jbHVkZSBkZWdyZWUgZm9yIGV2YWx1YXRpb24uIEJ1dCB3aGF0IGFyZSBhbGwgdGhlc2UgZWZmZWN0cz8gDQotICAgIHNob3VsZCBiZSBhYmxlIHRvIGNhbGN1bGF0ZSBzdGF0aXN0aWMgZm9yIGVhY2ggZWZmZWN0IGZvciBhbiBlZ28gaW4gYSBuZXR3b3JrLi4uIE1hdGhlbWF0aWNhbCBmb3JtdWxhIGluIGNoYXB0ZXIgMTIuIA0KDQoNCmBgYHtyfQ0KZWZmZWN0c0RvY3VtZW50YXRpb24obXllZmYpDQpgYGANCg0KDQpNYWtlIHN1cmUgdG8gdW5kZXJzdGFuZCBvdXQgZGVncmVlIGFuZCByZWNpcHJvY2l0eSBlZmZlY3RzIC0gc3RhdGlzdGljcyAtIHdpbGwgcGxheSBhcm91bmQgd2l0aCB0aGlzIG5leHQgd2Vlay4gTmVlZCB0byB0aGluayBvZiB0aGVvcnkgZm9yIHdoaWNoIHN0YXRpc3RpY3MgYXJlIHJlbGV2YW50LiANCi0gICAgTG9vayBhdCBsaXRlcmF0dXJlIGZvciBzdGF0aXN0aWNzLCB0aGluayBhYm91dCBpdCwgcGxheSBhbmQgc2VlIGlmIGVmZmVjdHMgZXhpc3RzIA0KLSAgICBob3cgd29yayBpbiByZWFsaXR5PyBwcm9wb3NlIGlkZWEsIHdyaXRlIG5vdGF0aW9uLCBzZWUgaWYgZWZmZWN0IGV4aXN0cyBpbiBtYW51YWwsIGV0Yy4gTG90cyBvZiBub3RhdGlvbiBiZWNhdXNlIGV2ZXJ5b25lIGlzIGxvb2tpbmcgZm9yIHRoZWlyIG93biBlZmZlY3RzLiANCi0gICAgbmVlZCB0byBpbmNsdWRlIG1vcmUgZWZmZWN0cyBpZiB3aGF0IHRvLiANCg0KYGBge3J9DQoNCmBgYA0KDQoNCg0KIyBTdGVwIDM6IExvb2sgYXQgaW50aWFsIGRhdGENCi0gICAgZ29vZCBmb3IgZGVjaWRpbmcgc3RhdGlzdGljcyB0byB1c2UuIA0KYGBge3J9DQpwcmludDAxUmVwb3J0KG15ZGF0YSkNCg0KIyBnaXZlcyBpbml0aWFsIGRlc2NyaXB0aW9uIG9mIGRhdGEgDQojIHJlYWRpbmcgbmV0d29yayB2YXJpYWJsZXMgLCBjb3ZhcmlhdGVzLCBkZW5zaXR5IG1lYXN1cmVzL2NoYW5nZXMgaW4gbmV0d29ya3MsIHRpZSBjaGFuZ2VzIGJldHdlZW4gc3Vic2VxdWVudCBvYnNlcnZhdGlvbnMuLi4gY2FsY3VsYXRlIGhvdyBtdWNoIG5ldHdvcmtzIGNoYW5nZWQgb3ZlciB0aW1lLiANCiMgZG9udCB1c2UgYmFsYW5jZSBjYWxjdWxhdGlvbiANCmBgYA0KDQojIFN0ZXAgNDogQWRkIGVmZmVjdHMNCg0KYGBge3J9DQpteWVmZiA8LSBpbmNsdWRlRWZmZWN0cyhteWVmZiwgaXNvbGF0ZU5ldCwgaW5Qb3AsIG91dEFjdCkNCg0KI291dEFjdCAtIG91dGRlZ3JlZSByZWxhdGVkIGFjdGl2aXR5IA0KYGBgDQoNCm91dEFjdA0KLSBsb29rIGF0IHRoZSBudW1iZXIgb2YgdGltZXMgSSBoYXZlIGFuZCBzcXVhcmUgdGhhdDogZXNwZWNpYWxseSB0aGUgcGVvcGxlIHRoYXQgaGF2ZSBhIGxvdCBvZiB0aWVzIHdpbGwgc2VuZCBhIGxvdCBvZiB0aWVzLiANCi0gZXZhbHVhdGlvbiBmdW5jdGlvbiBvZiB0aWUxIDAgdGllcywgYW5kIHRpZTEgNCB0aWVzIC0gdGhlbiBhdCB0MiBwZW9wbGUgd2hvIGhhdmUgdGllcyBhcmUgbW9yZSBsaWtlbHkgdG8gc2VuZCBtb3JlIHRpZXMgDQoNCldlIGtub3cgdGllIGRpc3RyaWJ1dGlvbnMgYXJlIHNrZXdlZCwgc29tZSBwZW9wbGUgc2VuZCBhIGxvdCBvZiB0aWVzIGFuZCBvdGhlcnMgZG9udC4gDQoNCmluUG9wOiBpbiBkZWdyZWUgYWN0aXZpdHk6IHBlb3BsZSB3aG8gcmVjZWl2ZSBhIGxvdCBvZiBpbi1kZWdyZWVzIHNlbmQgYSBsb3Qgb2Ygb3V0LWRlZ3JlZXMgDQoNCmlzb2xhdGVOZXQ6IHBlb3BsZSB3aXRob3V0IGEgbG90IG9mIGluZGVncmVlIG5ldHMuIA0KDQoNCg0KQ2FuIHNlZSB0aGF0IHN0YXJ0aW5nIHZhbHVlcyBhcmUgMCAtLSBoeXBvdGhlc2lzIHRlc3RpbmcgDQoNCiMgU3RlcCA1OiBFc3RpbWF0aW9uDQoNCmBgYHtyfQ0KbXlBbGdvcml0aG0gPC0gc2llbmFBbGdvcml0aG1DcmVhdGUocHJvam5hbWUgPSAidGVzdCIpDQoNCiMgZGVmaW5lIGFsZ29yaXRobSB0aGF0IHNheXMgaG93IEkgd2FudCB0byBlc3RpbWF0ZSBteSBtb2RlbC4gd2lsbCB1c2UgZGVmYXVsdHMuIA0KDQphbnNNMSA8LSBzaWVuYTA3KG15QWxnb3JpdGhtLCBkYXRhID0gbXlkYXRhLCBlZmZlY3RzID0gbXllZmYsIHJldHVybkRlcHMgPSBUUlVFKQ0KIyB0aGVuIHJ1biBpdCB0byBzZWUgDQoNCmFuc00xDQoNCmBgYA0KTm93IGhhdmUgZmlyc3QgZXN0aW1hdGVkIFJzaWVuYSBtb2RlbCEgDQoNCg0KLSBzZWU6bmVnYXRpdmUgb3V0IGRlZ3JlZSANCi0gMi40IHJlY2lwcm9jaXR5OiBpcyBpbXBvcnRhbnQgdGhlbiBpbiB0aGlzIG1vZGVsIA0KLSBpbmRlZ3JlZSBwb3B1bGF0eSBpcyBwb3B1bGFyIGJ1dCBub3Qgc2lnbmlmaWNhbnQuLi4gDQoNCmlmIHNpZ25pZmljYW50OiBtb3JlIGluZGVncmVlcy0gbW9yZSBsaWtlbHkgdG8gc2VuZCBsYXRlci4gcGVvcGxlIHdpdGggbW9yZSBvdXQtZGVncmVlcyAtIG1vcmUgbGlrZWx5IHRvIHNlbmQgbGVzcyAobmVnYXRpdmUpLiBpc29sYXRlIG1vcmUgbGlrZWx5IHRvIGJlIGFsb25lLiANCg0KDQpOZWVkIHRvIHRoaW5rIG9mIG1vZGVsIHRoYXQgbWFrZXMgc2Vuc2UgaW4gdGhpcw0KDQoNCmBgYHtyfQ0KDQpgYGANCg0KUkVWSUVXSU5HIFJTSUVOQSBOT1cNCi0gICBuZWdhdGl2ZSBkZWdyZWUgLSBkZW5zaXR5IGlzIGxlc3MgdGhhbiAuNSANCi0gICBpbnRlcnByZXRhdGlvbnMgDQotICAgTWFpbGluZyBsaXN0IGZvciBUT00NCg0KLSAgIE5vdzogcmUtcmVhZCBjaGFwdGVyIDIgYW5kIGNoYXB0ZXIgNSANCg0KQWZ0ZXJub29uOiBwbGF5IHdpdGggZXN0aW1hdGluZyBvdXIgb3duIG1vZGVscyANCk5pY2UgdG8gZG8gd2l0aCBvdXIgb3duIGRhdGEgLSBjb2xsYWJvcmF0aW9uIG5ldHdvcmtzLiANCkxvZ2ljIG9mIFJTSUVOQTogdG9vayBhY3RvciBvcmllbnRlZCBhcHByb2FjaCAtIHdvcmtzIGlmIHRpZXMgYXJlIGRpcmVjdGVkLiBpZiB1bmRpcmVjdGVkIG5ldHdvcmssIGxvZ2ljIGlzIGRpZmZlcmVudDogdGhlIGFjdG9yIGRlY2lkaW5nIG9uIHVuZGlyZWN0ZWQgdGllIGlzIGRpZmZpY3VsdC4gQWR2aXNlOiBmb3Igbm93IHRyZWF0IGFzIHVuZGlyZWN0ZWQgLSBhbmQgdGhlbiBldmFsdWF0ZSB0aWUuIA0KdW5kaXJlY3RlZCB0aWUgYnkgcmVhY2ggY29uc2Vuc3VzLCBmb3JjZWQgaW50byBjb25jZW5zdXMsIGV0YyAtIHJlY2lwcm9jaXR5IG1hdHRlcnMgbGVzcyBub3cuIA0KDQpgYGB7cn0NCg0KYGBgDQoNCiMgTm93IHBsYXkgd2l0aCBpdCANCg0KYGBge3J9DQoNCg0KYGBgDQoNCg0KYGBge3J9DQpgYGANCg0KDQpOb3cgLSByZWZlcmVuY2luZyB3ZWIgc2NyYXBpbmcgc2l0ZSANCg0KYGBge3J9DQpmY29sbmV0IDwtIGZ1bmN0aW9uKGRhdGEgPSBzY2hvbGFycywgdW5pdmVyc2l0eSA9ICJSVSIsIGRpc2NpcGxpbmUgPSAic29jaW9sb2d5Iiwgd2F2ZXMgPSBsaXN0KGMoMjAxNSwNCiAgICAyMDE4KSwgYygyMDE5LCAyMDIzKSksIHR5cGUgPSBjKCJmaXJzdCIpKSB7DQoNCiAgICAjIHN0ZXAgMQ0KICAgIGRlbW9ncmFwaGljcyA8LSBkby5jYWxsKHJiaW5kLmRhdGEuZnJhbWUsIGRhdGEkZGVtb2dyYXBoaWNzKQ0KICAgIGRlbW9ncmFwaGljcyA8LSBkZW1vZ3JhcGhpY3MgJT4lDQogICAgICAgIG11dGF0ZShVbml2ZXJzaXRlaXQxLjIyID0gcmVwbGFjZShVbml2ZXJzaXRlaXQxLjIyLCBpcy5uYShVbml2ZXJzaXRlaXQxLjIyKSwgIiIpLCBVbml2ZXJzaXRlaXQyLjIyID0gcmVwbGFjZShVbml2ZXJzaXRlaXQyLjIyLA0KICAgICAgICAgICAgaXMubmEoVW5pdmVyc2l0ZWl0Mi4yMiksICIiKSwgVW5pdmVyc2l0ZWl0MS4yNCA9IHJlcGxhY2UoVW5pdmVyc2l0ZWl0MS4yNCwgaXMubmEoVW5pdmVyc2l0ZWl0MS4yNCksDQogICAgICAgICAgICAiIiksIFVuaXZlcnNpdGVpdDIuMjQgPSByZXBsYWNlKFVuaXZlcnNpdGVpdDIuMjQsIGlzLm5hKFVuaXZlcnNpdGVpdDIuMjQpLCAiIiksIGRpc2NpcGxpbmUuMjIgPSByZXBsYWNlKGRpc2NpcGxpbmUuMjIsDQogICAgICAgICAgICBpcy5uYShkaXNjaXBsaW5lLjIyKSwgIiIpLCBkaXNjaXBsaW5lLjI0ID0gcmVwbGFjZShkaXNjaXBsaW5lLjI0LCBpcy5uYShkaXNjaXBsaW5lLjI0KSwgIiIpKQ0KDQogICAgc2FtcGxlIDwtIHdoaWNoKChkZW1vZ3JhcGhpY3MkVW5pdmVyc2l0ZWl0MS4yMiAlaW4lIHVuaXZlcnNpdHkgfCBkZW1vZ3JhcGhpY3MkVW5pdmVyc2l0ZWl0Mi4yMiAlaW4lDQogICAgICAgIHVuaXZlcnNpdHkgfCBkZW1vZ3JhcGhpY3MkVW5pdmVyc2l0ZWl0MS4yNCAlaW4lIHVuaXZlcnNpdHkgfCBkZW1vZ3JhcGhpY3MkVW5pdmVyc2l0ZWl0Mi4yNCAlaW4lDQogICAgICAgIHVuaXZlcnNpdHkpICYgKGRlbW9ncmFwaGljcyRkaXNjaXBsaW5lLjIyICVpbiUgZGlzY2lwbGluZSB8IGRlbW9ncmFwaGljcyRkaXNjaXBsaW5lLjI0ICVpbiUgZGlzY2lwbGluZSkpDQoNCiAgICBkZW1vZ3JhcGhpY3Nfc29jIDwtIGRlbW9ncmFwaGljc1tzYW1wbGUsIF0NCiAgICBzY2hvbGFyc19zZWwgPC0gbGFwcGx5KHNjaG9sYXJzLCAiWyIsIHNhbXBsZSkNCg0KICAgICMgc3RlcCAyDQogICAgaWRzIDwtIGRlbW9ncmFwaGljc19zb2MkYXVfaWQNCiAgICBud2F2ZXMgPC0gbGVuZ3RoKHdhdmVzKQ0KICAgIG5ldHMgPC0gYXJyYXkoMCwgZGltID0gYyhud2F2ZXMsIGxlbmd0aChpZHMpLCBsZW5ndGgoaWRzKSksIGRpbW5hbWVzID0gbGlzdCh3YXZlID0gMTpud2F2ZXMsIGlkcywNCiAgICAgICAgaWRzKSkNCiAgICBkaW1uYW1lcyhuZXRzKQ0KDQogICAgIyBzdGVwIDMNCiAgICBkZl93b3JrcyA8LSB0aWJibGUod29ya3NfaWQgPSB1bmxpc3QobGFwcGx5KHNjaG9sYXJzX3NlbCR3b3JrLCBmdW5jdGlvbihsKSBsJGlkKSksIHdvcmtzX2F1dGhvciA9IHVubGlzdChsYXBwbHkoc2Nob2xhcnNfc2VsJHdvcmssDQogICAgICAgIGZ1bmN0aW9uKGwpIGwkYXV0aG9yKSwgcmVjdXJzaXZlID0gRkFMU0UpLCB3b3Jrc195ZWFyID0gdW5saXN0KGxhcHBseShzY2hvbGFyc19zZWwkd29yaywgZnVuY3Rpb24obCkgbCRwdWJsaWNhdGlvbl95ZWFyKSwNCiAgICAgICAgcmVjdXJzaXZlID0gRkFMU0UpKQ0KDQogICAgZGZfd29ya3MgPC0gZGZfd29ya3NbIWR1cGxpY2F0ZWQoZGZfd29ya3MpLCBdDQoNCiAgICAjIHN0ZXAgNA0KICAgIGlmICh0eXBlID09ICJmaXJzdCIpIHsNCiAgICAgICAgZm9yIChqIGluIDE6bndhdmVzKSB7DQogICAgICAgICAgICBkZl93b3Jrc193IDwtIGRmX3dvcmtzW2RmX3dvcmtzJHdvcmtzX3llYXIgPj0gd2F2ZXNbW2pdXVsxXSAmIGRmX3dvcmtzJHdvcmtzX3llYXIgPD0gd2F2ZXNbW2pdXVsyXSwNCiAgICAgICAgICAgICAgICBdDQogICAgICAgICAgICBmb3IgKGkgaW4gMTpucm93KGRmX3dvcmtzX3cpKSB7DQogICAgICAgICAgICAgICAgZWdvIDwtIGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWRbMV0NCiAgICAgICAgICAgICAgICBhbHRlcnMgPC0gZGZfd29ya3NfdyR3b3Jrc19hdXRob3JbaV1bWzFdXSRhdV9pZFstMV0NCiAgICAgICAgICAgICAgICBpZiAoc3VtKGlkcyAlaW4lIGVnbykgPiAwICYgc3VtKGlkcyAlaW4lIGFsdGVycykgPiAwKSB7DQogICAgICAgICAgICAgICAgICBuZXRzW2osIHdoaWNoKGlkcyAlaW4lIGVnbyksIHdoaWNoKGlkcyAlaW4lIGFsdGVycyldIDwtIDENCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQoNCiAgICBpZiAodHlwZSA9PSAibGFzdCIpIHsNCiAgICAgICAgZm9yIChqIGluIDE6bndhdmVzKSB7DQogICAgICAgICAgICBkZl93b3Jrc193IDwtIGRmX3dvcmtzW2RmX3dvcmtzJHdvcmtzX3llYXIgPj0gd2F2ZXNbW2pdXVsxXSAmIGRmX3dvcmtzJHdvcmtzX3llYXIgPD0gd2F2ZXNbW2pdXVsyXSwNCiAgICAgICAgICAgICAgICBdDQogICAgICAgICAgICBmb3IgKGkgaW4gMTpucm93KGRmX3dvcmtzX3cpKSB7DQogICAgICAgICAgICAgICAgZWdvIDwtIHJldihkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkKVsxXQ0KICAgICAgICAgICAgICAgIGFsdGVycyA8LSByZXYoZGZfd29ya3NfdyR3b3Jrc19hdXRob3JbaV1bWzFdXSRhdV9pZClbLTFdDQogICAgICAgICAgICAgICAgaWYgKHN1bShpZHMgJWluJSBlZ28pID4gMCAmIHN1bShpZHMgJWluJSBhbHRlcnMpID4gMCkgew0KICAgICAgICAgICAgICAgICAgbmV0c1tqLCB3aGljaChpZHMgJWluJSBlZ28pLCB3aGljaChpZHMgJWluJSBhbHRlcnMpXSA8LSAxDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgaWYgKHR5cGUgPT0gImFsbCIpIHsNCiAgICAgICAgZm9yIChqIGluIDE6bndhdmVzKSB7DQogICAgICAgICAgICBkZl93b3Jrc193IDwtIGRmX3dvcmtzW2RmX3dvcmtzJHdvcmtzX3llYXIgPj0gd2F2ZXNbW2pdXVsxXSAmIGRmX3dvcmtzJHdvcmtzX3llYXIgPD0gd2F2ZXNbW2pdXVsyXSwNCiAgICAgICAgICAgICAgICBdDQogICAgICAgICAgICBmb3IgKGkgaW4gMTpucm93KGRmX3dvcmtzX3cpKSB7DQogICAgICAgICAgICAgICAgZWdvcyA8LSBkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkDQogICAgICAgICAgICAgICAgaWYgKHN1bShpZHMgJWluJSBlZ29zKSA+IDApIHsNCiAgICAgICAgICAgICAgICAgIG5ldHNbaiwgd2hpY2goaWRzICVpbiUgZWdvcyksIHdoaWNoKGlkcyAlaW4lIGVnb3MpXSA8LSAxDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KICAgIG91dHB1dCA8LSBsaXN0KCkNCiAgICBvdXRwdXQkZGF0YSA8LSBzY2hvbGFyc19zZWwNCiAgICBvdXRwdXQkbmV0cyA8LSBuZXRzDQogICAgcmV0dXJuKG91dHB1dCkNCn0NCmBgYA0KDQoNCkV4YW1wbGUgaW4gY2xhc3MgZnJvbSAxMCBPY3RvYmVyDQpTaWVuYSBkZXBlbmRlbnQgdmFyaWFibGUgDQoNCmBgYHtyfQ0KIyBTdGVwIDE6IGxvYWQgZGF0YQ0KbGlicmFyeShSU2llbmEpDQo/c2llbmFEZXBlbmRlbnQgI2xvb2sgZm9yIGV4YW1wbGVzIC0gc2NyaXB0IGZvciBob3cgdG8gcnVuIHN0dWZmIA0KDQoNCiMgdGhlbiBjaGVjayB3YXZlcyBhdmFpbGFibGUNCnM1MDEgI25ldHdvcmsgYXQgdGltZXBvaW50IDENCnM1MDIgI25ldHdvcmsgYXQgdGltZXBvaW50IDINCnM1MDMgI25ldHdvcmsgYXQgdGltZXBvaW50IA0KDQoNCm15bmV0MSA8LSBzaWVuYURlcGVuZGVudChhcnJheShjKHM1MDEsIHM1MDIsIHM1MDMpLCBkaW09Yyg1MCwgNTAsIDMpKSkNCm15YmVoIDwtIHNpZW5hRGVwZW5kZW50KHM1MGEsIHR5cGU9ImJlaGF2aW9yIikNCg0KICMgbG9vayBmb3Igc21va2luZyBhbmQgZHJpbmtpbmcgYmVoYXZpb3JzDQoNCnNtb2tlIDwtIHM1MHMgI3RpbWUgdmFyeWluZyBjb3ZhcmlhdGUuIFRpbWUgY29uc3RhbnQgY292YXIgLSB2YXJDb3Zhcg0Kc21va2UgPC0gdmFyQ292YXIoczUwcykNCg0KbXlkYXRhX2V4YW1wbGUgPC0gc2llbmFEYXRhQ3JlYXRlKG15bmV0MSwgbXliZWgsIHNtb2tlKQ0KDQoNCg0KIyBTdGVwIDI6IGxvb2sgYXQgZGF0YQ0KI3ByaW50IHJlcG9ydCBvbiBkYXRhIHJlcG9ydHMNCg0KcHJpbnQwMVJlcG9ydChteWRhdGFfZXhhbXBsZSkNCg0KDQojIFN0ZXAgMzogYWRkIGVmZmVjdHMgDQpteWVmZl9leGFtcGxlIDwtIGdldEVmZmVjdHMobXlkYXRhX2V4YW1wbGUpDQpteWVmZl9leGFtcGxlDQoNCg0KDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAic21va2UiKQ0KbXllZmZfZXhhbXBsZQ0KDQoNCiNtYWtlIGFsZ29yaXRobSB0byB0aGVuIGVzdGltYXRlIGl0DQphbGdvX2V4IDwtIHNpZW5hQWxnb3JpdGhtQ3JlYXRlKHByb2puYW1lID0gInRlc3RfZXgiKQ0KYW5zd2VyX2V4IDwtIHNpZW5hMDcoYWxnb19leCwgZGF0YT1teWRhdGFfZXhhbXBsZSwgZWZmZWN0cz1teWVmZl9leGFtcGxlLCByZXR1cm5EZXBzID0gVFJVRSkNCg0KYW5zd2VyX2V4DQoNCg0KI2RvZXMgaXQgY2hhbmdlIGlmIGRlcGVuZGVudCBYIA0KbXllZmZfZXhhbXBsZSA8LSBpbmNsdWRlRWZmZWN0cyhteWVmZl9leGFtcGxlLCB1bmVxdWFsWCwgbmFtZT0ibXluZXQxIiwgaW50ZXJhY3Rpb24xID0gIm15YmVoIikgI25hbWUgPSBuZXR3b3JrIGRlcGVuZGVudCB2YXJpYWJsZSwgaW50ZXJhY3Rpb24gMSBpcyBjb3ZhcmlhdGUgKHNtb2tpbmcpIC0gaWYgaGF2ZSBtdWx0aXBsZSBuZXRvd3JrcywgdGhlbiBjb3VsZCBoYXZlIHVuZXF1YWxYIHdpdGggcmVzcGVjdCB0byBYLiBXZSByZXBsYWNlZCBzbW9rZSB3aXRoIG15IGJlaGF2aW9yLCBhbmQgcmVydW4gdGhlIHNpZW5hIG1vZGVsLiBUaGlzIGlzIGFuIGFsZ29yaXRobSwgY2FuIGFzayBSU2llbmEgdG8gcmVmZXJlbmNlIHByZXZpb3VzIHJlc3VsdCB3aXRoICdwcmV2YW5zPUFOUycgYWZ0ZXIgcmV0dXJuRGVwdHMgPSBUUlVFDQphbnN3ZXJfZXggPC0gc2llbmEwNyhhbGdvX2V4LCBkYXRhPW15ZGF0YV9leGFtcGxlLCBlZmZlY3RzPW15ZWZmX2V4YW1wbGUsIHJldHVybkRlcHMgPSBUUlVFKQ0KDQphbnN3ZXJfZXgNCiMgbG9va2luZyBhdCByZXN1bHRzLCBteWJlaCA9IGRyaW5raW5nIC0tIGVnbyBsZXNzIGxpa2VseSB0byBzcGVuZCB0aW1lIHdpdGggcGVvcGxlIHdobyBkcmluayBtb3JlIG9yIGxlc3MgdGhhbiB0aGVtLiBlZ28gYWxzbyBsZXNzIGxpa2VseSB0byBzcGVuZCB0aW1lIHdpdGggcGVvcGxlIHdobyBzbW9rZSBtb3JlIG9yIGxlc3MsIHRvIGEgbGVzc2VyIGV4dGVudC4gQ2FuIHVzZSB1bmVxdWFsWCBmb3IgZGVwZW5kZW50IHZhcmlhYmxlcyBhbmQgY292YXJpYXRlcy4ga2V5IGRpZmZlcmVuY2UgaW4gZXN0aW1hdGlvbiBwcm9jZWR1cmU6IA0KIyB3ZSBhcmUgYWxzbyBtb2RlbGluZyBiZWhhdmlvcmFsIHJlc3VsdHMgLSBiZWhhdmlvciBjaGFuZ2luZyBvdmVyIHRpbWUsIHNpbXVsYXRlZCB2aWEgbWluaXN0ZXAgbG9naWMgKG9uZSBzdGVwIHVwIG9yIGRvd24pLiBUaGUgY3J1Y2lhbCBkaWZmZXJlbmNlOiBkdXJpbmcgdGhlIGFsZ29yaXRobSANCiNJZiBjb3VudCBzdGF0aXN0aWMgZm9yIHNtb2tlLCB0aGVuIGJldHdlZW4gdGltZSBwb2ludCAxIGFuZCAyIHdlIHVzZSB2YWx1ZSBmcm9tIHRpbWVwb2ludCAxLiBiZXR3ZWVuIDItMywgdXNlIHRpbWUgcG9pbnQgMi4gQnV0IHdpdGhpbiB0aGUgdmFyaWFibGUsIHRoZSBlZ28gbGV2ZWwgYmVoYXZpb3IgaXMgY2hhbmdpbmcuIGlzIG5vdCB1c2luZyB0aGUgdmFsdWUgYXMgb2JzZXJ2ZWQgYXQgdDEgLSBpdCBpcyB1c2luZyB0aGUgdmFsdWUgYXMgaXMgY3VycmVudGx5IHNpbXVsYXRlZC4gDQoNCg0KDQoNCg0KI2NvdWxkIGV4Y2x1ZGUgdmFyaWFibGUgdG8gdGhlbiBpbmNsdWRlIGFzIGNvdmFyaWF0ZSBlZmZlY3QuIA0KDQpteWJlaCA8LSBzaWVuYURlcGVuZGVudChzNTBhLCB0eXBlPSJiZWhhdmlvciIpICNkZWZpbmVkIGFzIGRlcGVuZGVudCB2YXJpYWJsZSANCmRyaW5raW5nIDwtIHZhckNvdmFyKHM1MGEpICNkZWZpbmVkIGFzIGNvdmFyaWF0ZSB2YXJpYWJsZSANCg0KI3VwZGF0ZSBkYXRhIG9iamVjdDogDQpteWRhdGFfZXhhbXBsZSA8LSBzaWVuYURhdGFDcmVhdGUobXluZXQxLCBteWJlaCwgZHJpbmtpbmcsIHNtb2tlKQ0KDQoNCiNhbmQgZWZmZWN0cyBvYmplY3Q6IA0KbXllZmZfZXhhbXBsZSA8LSBpbmNsdWRlRWZmZWN0cyhteWVmZl9leGFtcGxlLCB1bmVxdWFsWCwgbmFtZT0ibXluZXQxIiwgaW50ZXJhY3Rpb24xID0gInNtb2tlIikNCg0KbXllZmZfZXhhbXBsZSA8LSBpbmNsdWRlRWZmZWN0cyhteWVmZl9leGFtcGxlLCB1bmVxdWFsWCwgbmFtZT0ibXluZXQxIiwgaW50ZXJhY3Rpb24xID0gImRyaW5raW5nIikNCg0KYWxnb19leDIgPC0gc2llbmFBbGdvcml0aG1DcmVhdGUocHJvam5hbWUgPSAidGVzdF9leCIpDQoNCmFuc3dlcl9leCA8LSBzaWVuYTA3KGFsZ29fZXgyLCBkYXRhPW15ZGF0YV9leGFtcGxlLCBlZmZlY3RzPW15ZWZmX2V4YW1wbGUsIHJldHVybkRlcHMgPSBUUlVFKQ0KYW5zd2VyX2V4DQoNCiN0aGVuIHRoZSBuZXR3b3JrIGR5bmFtaWNzIGNoYW5nZSANCiMgaW50ZXJwcmV0YXRpb24gb2YgdGhlIHJhdGUgY29uc3RhbnQgLSB0aGUgYXZlcmFnZSBhbW91bnQgb2YgbWluaXN0ZXBzIGVhY2ggZWdvIGlzIG1ha2luZyBiZXR3ZWVuIHRoZSB0d28gb2JzZXJ2YXRpb25zDQoNCiNiZWhhdmlvcmFsIGR5bmFtaWNzOiANCiMgdGhlIHJhdGUgY29uc3RhbnQ6IHRoZSBudW1iZXIgb2Ygc3RlcHMgaW4gdGhlIGJlaGF2aW9yYWwgYXNwZWN0IA0KDQojc3RhdGlzdGljIGZvciBsaW5lYXIgc2hhcGUgLSBsaW5lYXIgc2hhcGUgZWZmZWN0IC0gdGhlIHZhbHVlIG9mIHRoZSAqY2VudGVyZWQqIGJlaGF2aW9yYWwgdmFyaWFibGUgKGF2ZXJhZ2UgaW4gdGhlIHRvdGFsIHNhbXBsZSkuIA0KIyBpZiBwb3NpdGl2ZSwgdHJ5IHRvIGluY3JlYXNlIGJlaGF2aW9yLiBlZmZlY3QgaXMgejEgKHplZCBzY29yZSksIHdpdGggdGhlIG9wdGlvbnMgb2YgMSwgMCwgb3IgLTEuIGJlaGF2aW9yIGluY3JlYXNlcyBiZWNhdXNlIHBvc2l0aXZlbHkgZXZhbHVhdGVzIDEgbW9yZSB0aGFuIDAsIG1vcmUgdGhhbiAtMS4gQXQgc29tZSBwb2ludCwgdGhvdWdoLCBiZWhhdmlvciB3aWxsIHN0b3AgaW5jcmVhc2luZyAtIHRoYXQgaXMgejIgKHNxdWFyZWQhKS4gc28sIHBhcmFtZXRlciBtb2RlcmF0ZXMgaXRzZWxmIHdpdGggdGltZT8/IA0KDQojIHRoZXNlIGFyZSB0aGUgbWluaW11bSBlZmZlY3RzIHRvIGluY2x1ZGUsIGJlY2F1c2UgaXQgcHJlZGljdHMgbWVhbiB2YWx1ZSBvYnNlcnZlIGluIGRhdGFzZXQuIDIgcGFyYW1ldGVycyAtIGVzdGltYXRlIG1lYW4gYmVoYXZpb3IuIGJhc2VkIG9uIG1vZGVsIHJlc3VsdHMsIHdoYXQgaXMgdGhlIG1lYW4gdmFsdWUuIA0KDQojIGJlaGF2aW9yYWwgdmFyaWFibGVzIGluIGRhdGFzZXQgLSBldmVyeXRoaW5nIG9ic2VydmVkIHRoYXQgY2hhbmdlcy4gZXguLCBwb3NpdGlvbiAoZnVuY3RpZSksIGNpdGF0aW9ucywgaW50ZXJkaXNjaXBsaW5hcml0eSBzY29yZS4gUHJvYmxlbTogaXMgdGltZSB3aW5kb3cgbGFyZ2UgZW5vdWdodCB0byBzZWUgY2hhbmdlPyBhbmQgb3ZlciB0aW1lLCBiZWhhdmlvcmFsIHZhcmlhYmxlIGlzIG9ubHkgY2hhbmdpbmcgLSB3aGljaCB0aGVuIG11c3QgYmUgY2FsY3VsYXRlZCBhcyBjb250aW51b3VzIGRlcGVuZGVkIHZhcmlhYmxlLiANCg0KDQpgYGANCg0KDQo=